#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
二进制文件转图片转换器模块
"""

import os
import math
from PIL import Image
import numpy as np

class BinaryConverter:
    """
    二进制文件转图片转换器类
    """
    
    def __init__(self):
        """
        初始化转换器
        """
        pass
    
    def convert_to_image(self, binary_file_path, width, mode="RGB"):
        """
        将二进制文件转换为图片
        
        参数:
            binary_file_path (str): 二进制文件路径
            width (int): 输出图片宽度
            mode (str): 图片模式，可以是 'L'（灰度）, 'RGB' 或 'RGBA'
            
        返回:
            PIL.Image: 转换后的图片对象
        """
        # 检查文件是否存在
        if not os.path.exists(binary_file_path):
            raise FileNotFoundError(f"找不到文件: {binary_file_path}")
        
        # 检查参数
        if width <= 0:
            raise ValueError("宽度必须大于0")
        
        # 确定每个像素的字节数
        bytes_per_pixel = 1
        if mode == "RGB":
            bytes_per_pixel = 3
        elif mode == "RGBA":
            bytes_per_pixel = 4
        
        # 读取二进制文件
        with open(binary_file_path, "rb") as f:
            binary_data = f.read()
        
        # 计算图片尺寸
        file_size = len(binary_data)
        height = math.ceil(file_size / (width * bytes_per_pixel))
        
        # 如果文件大小不是宽度*高度*每像素字节数的整数倍，需要填充
        total_pixels = width * height
        total_bytes_needed = total_pixels * bytes_per_pixel
        
        # 如果需要填充，使用零填充
        if len(binary_data) < total_bytes_needed:
            padding = b'\x00' * (total_bytes_needed - len(binary_data))
            binary_data += padding
        
        # 将二进制数据转换为numpy数组
        if mode == "L":
            # 灰度模式
            array = np.frombuffer(binary_data[:total_bytes_needed], dtype=np.uint8)
            array = array.reshape((height, width))
        elif mode == "RGB":
            # RGB模式
            array = np.frombuffer(binary_data[:total_bytes_needed], dtype=np.uint8)
            array = array.reshape((height, width, 3))
        elif mode == "RGBA":
            # RGBA模式
            array = np.frombuffer(binary_data[:total_bytes_needed], dtype=np.uint8)
            array = array.reshape((height, width, 4))
        else:
            raise ValueError(f"不支持的模式: {mode}")
        
        # 创建PIL图像
        image = Image.fromarray(array, mode=mode)
        return image
    
    def convert_to_binary(self, image_path, output_path=None):
        """
        将图片转换回二进制文件
        
        参数:
            image_path (str): 图片文件路径
            output_path (str, optional): 输出二进制文件路径
            
        返回:
            str: 输出文件路径
        """
        # 检查文件是否存在
        if not os.path.exists(image_path):
            raise FileNotFoundError(f"找不到文件: {image_path}")
        
        # 打开图片
        image = Image.open(image_path)
        
        # 将图片转换为二进制数据
        binary_data = image.tobytes()
        
        # 确定输出路径
        if output_path is None:
            base_name = os.path.splitext(os.path.basename(image_path))[0]
            output_path = f"{base_name}.bin"
        
        # 写入二进制文件
        with open(output_path, "wb") as f:
            f.write(binary_data)
        
        return output_path
